package juc.scenarios.startup.service.impl;

import juc.scenarios.startup.model.ServiceStatus;
import juc.scenarios.startup.model.ServiceCheckResult;
import juc.scenarios.startup.service.HealthCheckService;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.*;

/**
 * 服务启动检查管理器
 * 使用CountDownLatch协调多个服务的并发检查
 */
public class StartupCheckManager {

    public List<HealthCheckService> healthCheckServices;

    /**
     * 执行所有服务的健康检查
     *
     * @param timeout 超时时间（毫秒）
     * @return 检查结果
     */
    public ServiceCheckResult performStartupChecks(long timeout) {

        String checkId = UUID.randomUUID().toString();
        LocalDateTime startTime = LocalDateTime.now();

        // 创建CountDownLatch，计数器为服务数量
        CountDownLatch latch = new CountDownLatch(healthCheckServices.size());

        // 创建线程池执行检查任务
        ExecutorService executor = Executors.newFixedThreadPool(healthCheckServices.size());

        // 存储检查结果
        Map<String, ServiceStatus> checkResults = new ConcurrentHashMap<>();

        // 提交所有检查任务
        for (HealthCheckService service : healthCheckServices) {
            executor.submit(() -> {
                try {

                    // 执行检查，带超时控制
                    ServiceStatus status = performCheckWithTimeout(service, timeout);
                    checkResults.put(service.getServiceName(), status);


                } catch (Exception e) {

                    // 创建异常状态
                    ServiceStatus errorStatus = ServiceStatus.builder()
                            .serviceName(service.getServiceName())
                            .state(ServiceStatus.ServiceState.UNHEALTHY)
                            .message("检查异常: " + e.getMessage())
                            .startTime(LocalDateTime.now())
                            .endTime(LocalDateTime.now())
                            .duration(0L)
                            .build();

                    checkResults.put(service.getServiceName(), errorStatus);

                } finally {
                    // 无论成功失败，都要减少计数器
                    latch.countDown();
                }
            });
        }

        try {
            // 等待所有检查完成或超时
            boolean completed = latch.await(timeout, TimeUnit.MILLISECONDS);

            if (!completed) {

                // 处理超时的情况
                handleTimeoutServices(healthCheckServices, checkResults);
            }

        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        // 关闭线程池
        executor.shutdown();

        LocalDateTime endTime = LocalDateTime.now();
        long totalDuration = java.time.Duration.between(startTime, endTime).toMillis();

        // 统计结果
        ServiceCheckResult result = buildCheckResult(checkId, startTime, endTime, totalDuration, checkResults);


        return result;
    }

    /**
     * 执行带超时控制的检查
     */
    private ServiceStatus performCheckWithTimeout(HealthCheckService service, long timeout) {
        ExecutorService timeoutExecutor = Executors.newSingleThreadExecutor();

        try {
            Future<ServiceStatus> future = timeoutExecutor.submit(service::checkHealth);

            // 使用服务特定的超时时间或全局超时时间
            long serviceTimeout = Math.min(service.getTimeout(), timeout);
            return future.get(serviceTimeout, TimeUnit.MILLISECONDS);

        } catch (TimeoutException e) {
            return ServiceStatus.builder()
                    .serviceName(service.getServiceName())
                    .state(ServiceStatus.ServiceState.TIMEOUT)
                    .message("检查超时")
                    .startTime(LocalDateTime.now())
                    .endTime(LocalDateTime.now())
                    .duration(timeout)
                    .build();

        } catch (Exception e) {
            return ServiceStatus.builder()
                    .serviceName(service.getServiceName())
                    .state(ServiceStatus.ServiceState.UNHEALTHY)
                    .message("执行异常: " + e.getMessage())
                    .startTime(LocalDateTime.now())
                    .endTime(LocalDateTime.now())
                    .duration(0L)
                    .build();

        } finally {
            timeoutExecutor.shutdownNow();
        }
    }

    /**
     * 处理超时服务
     */
    private void handleTimeoutServices(List<HealthCheckService> services, Map<String, ServiceStatus> results) {
        for (HealthCheckService service : services) {
            if (!results.containsKey(service.getServiceName())) {
                // 如果服务还没有结果，说明还在检查中或超时
                ServiceStatus timeoutStatus = ServiceStatus.builder()
                        .serviceName(service.getServiceName())
                        .state(ServiceStatus.ServiceState.TIMEOUT)
                        .message("检查超时")
                        .startTime(LocalDateTime.now())
                        .endTime(LocalDateTime.now())
                        .duration(service.getTimeout())
                        .build();

                results.put(service.getServiceName(), timeoutStatus);
            }
        }
    }

    /**
     * 构建检查结果
     */
    private ServiceCheckResult buildCheckResult(String checkId, LocalDateTime startTime,
                                                LocalDateTime endTime, long totalDuration,
                                                Map<String, ServiceStatus> results) {

        long healthyCount = results.values().stream()
                .filter(status -> status.getState() == ServiceStatus.ServiceState.HEALTHY)
                .count();

        long unhealthyCount = results.values().stream()
                .filter(status -> status.getState() != ServiceStatus.ServiceState.HEALTHY)
                .count();

        return ServiceCheckResult.builder()
                .checkId(checkId)
                .totalServices(results.size())
                .healthyServices((int) healthyCount)
                .unhealthyServices((int) unhealthyCount)
                .startTime(startTime)
                .endTime(endTime)
                .totalDuration(totalDuration)
                .serviceStatusMap(results)
                .build();
    }

    /**
     * 快速检查方法（使用默认超时时间）
     */
    public ServiceCheckResult performQuickStartupChecks() {
        return performStartupChecks(10000L); // 默认10秒超时
    }
}